<template>
    <div>
        <div class="btns-box">
            <el-button type="primary" @click="measure('LineString')">测距</el-button>
            <el-button type="primary" @click="measure('Polygon')">测面</el-button>
            <el-button type="primary" @click="clearMeasure">清除测量轨迹</el-button>
        </div>
    </div>
</template>

<script>
    import 'ol/ol.css'
    import Draw from 'ol/interaction/Draw'
    import Overlay from 'ol/Overlay'
    import {Circle as CircleStyle, Fill, Stroke, Style} from 'ol/style'
    import {LineString, Polygon} from 'ol/geom'
    import {Vector as VectorSource} from 'ol/source'
    import {Vector as VectorLayer} from 'ol/layer'
    import {getArea, getLength} from 'ol/sphere'
    import {unByKey} from 'ol/Observable'


    let layerIndex = 0
    export default {
        name: 'Measure',
        props: {
            drawLineMap: {
                type: Object,
                default: () => {
                }
            }
        },
        data() {
            return {
                map: null,
                raster: null,
                vector: new VectorLayer({
                    source: new VectorSource(),
                    style: new Style({
                        fill: new Fill({
                            color: 'rgba(255, 255, 255, 0.2)'
                        }),
                        stroke: new Stroke({
                            color: '#ffcc33',
                            width: 2
                        }),
                        image: new CircleStyle({
                            radius: 7,
                            fill: new Fill({
                                color: '#ffcc33'
                            })
                        })
                    })
                }),
                sketch: null, // Currently drawn feature
                helpTooltipElement: null, // The help tooltip element.
                helpTooltip: null, // Overlay to show the help messages.
                measureTooltipElement: null, // The measure tooltip element.
                measureTooltip: null, // Overlay to show the measurement.
                // Message to show when the user is drawing a polygon.
                continuePolygonMsg: '单击继续绘制多边形',
                // Message to show when the user is drawing a line
                continueLineMsg: '单击继续绘制直线',
                draw: null, //global so we can remove it later
                listener: null,
                shapeType: null,
                drawCache: {},
            }
        },
        created() {
            setTimeout(() => {
                this.map = this.drawLineMap
                this.map.addLayer(this.vector)
            }, 1000)
        },
        methods: {
            // 测距、测面
            measure(type) {
                this.shapeType = type
                layerIndex++
                this.drawCache[layerIndex] = {
                    feature: null,
                    measureTooltip: null
                }
                if (this.draw) {
                    this.map.removeInteraction(this.draw)
                }
                // 添加map事件
                this.addMapEvent()
            },
            // 清除测量
            clearMeasure() {
                for (const i in this.drawCache) {
                    this.map.removeOverlay(this.drawCache[i].measureTooltip)
                    this.vector.getSource().removeFeature(this.drawCache[i].feature)
                }
                this.drawCache = {}
                layerIndex = 0
            },
            addMapEvent() {
                this.map.on('pointermove', (evt) => {
                    this.draw ? this.pointerMoveHandler(evt) : this.map.removeOverlay(this.helpTooltip)
                })
                this.map.getViewport().addEventListener('mouseout', () => {
                    this.helpTooltipElement && this.helpTooltipElement.classList.add('hidden')
                })
                this.addInteraction()
            },
            addInteraction() {
                this.draw = new Draw({
                    source: this.vector.getSource(),
                    type: this.shapeType,
                    style: new Style({
                        fill: new Fill({
                            color: 'rgba(255, 255, 255, 0.2)'
                        }),
                        stroke: new Stroke({
                            color: 'rgba(0, 0, 0, 0.5)',
                            lineDash: [10, 10],
                            width: 2
                        }),
                        image: new CircleStyle({
                            radius: 5,
                            stroke: new Stroke({
                                color: 'rgba(0, 0, 0, 0.7)'
                            }),
                            fill: new Fill({
                                color: 'rgba(255, 255, 255, 0.2)'
                            })
                        })
                    })
                })

                this.map.addInteraction(this.draw)
                this.createMeasureTooltip()
                this.createHelpTooltip()
                this.drawHandler()
            },
            /**
             * Handle pointer move.
             * @param {import('../src/ol/MapBrowserEvent').default} evt The event.
             */
            pointerMoveHandler(evt) {
                if (evt.dragging) {
                    return
                }
                /** @type {string} */
                var helpMsg = '单击开始绘图'

                if (this.sketch) {
                    var geom = this.sketch.getGeometry()
                    if (geom instanceof LineString) {
                        helpMsg = this.continueLineMsg
                    }
                }

                this.helpTooltipElement.innerHTML = helpMsg
                this.helpTooltip.setPosition(evt.coordinate)

                this.helpTooltipElement.classList.remove('hidden')
            },
            /**
             * Format length output.
             * @param {LineString} line The line.
             * @return {string} The formatted length.
             */
            formatLength(line) {
                const sourceProj = this.map.getView().getProjection() // 获取投影坐标系
                var length = getLength(line, {projection: sourceProj})
                var output
                if (length > 100) {
                    output = Math.round((length / 1000) * 100) / 100 + ' ' + 'km'
                } else {
                    output = Math.round(length * 100) / 100 + ' ' + 'm'
                }
                return output
            },
            /**
             * Format area output.
             * @param {Polygon} polygon The polygon.
             * @return {string} Formatted area.
             */
            formatArea(polygon) {
                const sourceProj = this.map.getView().getProjection() //获取投影坐标系
                const geom = polygon.clone().transform(sourceProj, 'EPSG:3857')
                const area = getArea(geom)

                let output
                if (area > 10000) {
                    output = Math.round((area / 1000000) * 100) / 100 + ' ' + 'km<sup>2</sup>'
                } else {
                    output = Math.round(area * 100) / 100 + ' ' + 'm<sup>2</sup>'
                }
                return output
            },
            /**
             * Creates a new measure tooltip
             */
            createMeasureTooltip() {
                if (this.measureTooltipElement) {
                    this.measureTooltipElement.parentNode.removeChild(this.measureTooltipElement)
                }
                this.measureTooltipElement = document.createElement('div')
                this.measureTooltipElement.className = 'ol-tooltip ol-tooltip-measure'
                this.measureTooltip = new Overlay({
                    element: this.measureTooltipElement,
                    offset: [0, -15],
                    positioning: 'bottom-center'
                })
                this.map.addOverlay(this.measureTooltip)
            },
            /**
             * Creates a new help tooltip
             */
            createHelpTooltip() {
                if (this.helpTooltipElement) {
                    this.helpTooltipElement.parentNode.removeChild(this.helpTooltipElement)
                }
                this.helpTooltipElement = document.createElement('div')
                this.helpTooltipElement.className = 'ol-tooltip hidden'
                this.helpTooltip = new Overlay({
                    element: this.helpTooltipElement,
                    offset: [15, 0],
                    positioning: 'center-left'
                })
                this.map.addOverlay(this.helpTooltip)
            },
            drawHandler() {
                this.draw.on('drawstart', (evt) => {
                    this.sketch = evt.feature
                    let tooltipCoord = evt.coordinate

                    this.listener = this.sketch.getGeometry().on('change', (evt) => {
                        let output
                        const geom = evt.target
                        if (geom instanceof LineString) {
                            output = this.formatLength(geom)
                            tooltipCoord = geom.getLastCoordinate()
                        } else if (geom instanceof Polygon) {
                            output = this.formatArea(geom)
                            tooltipCoord = geom.getInteriorPoint().getCoordinates()
                        }
                        const closeBtn =
                            '<i class=\'tooltip-close-btn tooltip-close-btn_' + layerIndex + '\' data-index=\'' + layerIndex + '\'></i>'
                        this.measureTooltipElement.innerHTML = output + closeBtn
                        this.measureTooltip.setPosition(tooltipCoord)
                        this.drawCache[layerIndex].measureTooltip = this.measureTooltip
                    })
                })

                this.draw.on('drawend', (evt) => {
                    this.drawCache[layerIndex].feature = evt.feature

                    this.measureTooltipElement.className = 'ol-tooltip ol-tooltip-static'
                    this.measureTooltip.setOffset([0, -7])
                    // unset sketch
                    this.sketch = null
                    // unset tooltip so that a new one can be created
                    this.measureTooltipElement = null
                    this.createMeasureTooltip()
                    unByKey(this.listener)
                    this.map.removeInteraction(this.draw)
                    this.draw = null

                    // 删除图层
                    const self = this
                    document.querySelector('.tooltip-close-btn_' + layerIndex).addEventListener('click', function () {
                        self.vector.getSource().removeFeature(self.drawCache[this.dataset.index].feature)
                        self.map1.removeOverlay(self.drawCache[this.dataset.index].measureTooltip)
                        delete self.drawCache[this.dataset.index]
                    })
                })
            }
        },
        mounted() {
        }

    }
</script>
<style lang="scss" scoped>
    .btns-box {
        float: left;
        margin-left: 5px;
    }

    //测距，测面
    ::v-deep .ol-tooltip {
        position: relative;
        background: rgba(0, 0, 0, 0.5);
        border-radius: 4px;
        color: white;
        padding: 4px 14px 4px 8px;
        opacity: 0.7;
        white-space: nowrap;
        font-size: 12px;
    }

    ::v-deep .ol-tooltip-measure {
        opacity: 1;
        font-weight: bold;
    }

    ::v-deep .ol-tooltip-static {
        background-color: #ffcc33;
        color: black;
        border: 1px solid white;
    }

    ::v-deep .ol-tooltip-measure:before,
    ::v-deep .ol-tooltip-static:before {
        border-top: 6px solid rgba(0, 0, 0, 0.5);
        border-right: 6px solid transparent;
        border-left: 6px solid transparent;
        content: '';
        position: absolute;
        bottom: -6px;
        margin-left: -5px;
        left: 50%;
    }

    ::v-deep .ol-tooltip-static:before {
        border-top-color: #ffcc33;
    }

    //测面、测距的样式
    ::v-deep .tooltip-close-btn {
        font-style: normal;
        position: absolute;
        color: #2d8cf0;
        right: 0px;
        top: -7px;
        font-weight: bold;
        font-size: 15px;
        cursor: pointer;

        &:hover {
            color: #fff;
        }
    }
</style>